﻿using ClumsyWordsPortableLibrary.Model;
using ClumsyWordsPortableLibrary.Shared;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace ClumsyWordsPortableLibrary.ViewModel
{
    public class MainViewModel : ViewModelBase
    {

        public MainViewModel(IFileStorage<ObservableCollection<TermDefinition>> collectionsFileStorage)
        {
            this.FileStorage = collectionsFileStorage;
            this.RecentItems = new ObservableCollection<TermDefinition>();
            this.FavouriteItems = new ObservableCollection<TermDefinition>();
            this.SearchResult = new TermDefinition();
        }

        public IFileStorage<ObservableCollection<TermDefinition>> FileStorage { get; private set; }

        /// <summary>
        /// A collection for items that have been recently looked up.
        /// </summary>
        public ObservableCollection<TermDefinition> RecentItems { get; private set; }

        /// <summary>
        /// A collection for items that have been added to favourites list
        /// </summary>
        public ObservableCollection<TermDefinition> FavouriteItems { get; private set; }

        /// <summary>
        /// The result of the last quick search.
        /// </summary>
        private TermDefinition _searchResult;
        public TermDefinition SearchResult
        {
            get { return this._searchResult; }

            set
            {
                this._searchResult = value;
                NotifyPropertyChanged("SearchResult");
            }
        }

        /// <summary>
        /// The current term that is being searched for.
        /// </summary>
        private string _searchTerm;
        public string SearchTerm
        {
            get { return this._searchTerm; }

            set
            {
                this._searchTerm = value;
                NotifyPropertyChanged("SearchTerm");
            }
        }

        /// <summary>
        /// Sends a request to the STANDS4 API and presents the result as a SearchResult
        /// </summary>
        /// <param name="word">The word that is being searched for</param>
        /// <returns></returns>
        public async Task<TermDefinition> CheckWordAsync(string word, string url)
        {
            //PartOfSpeechConverter converter = new PartOfSpeechConverter();

            HttpClient client = new HttpClient();

            HttpResponseMessage response = await client.GetAsync(url);
            string responseText = await response.Content.ReadAsStringAsync();
            //TODO : Check if there is a responseText before parsing it.

            XDocument doc = XDocument.Parse(responseText);
            if (doc.Element("results").Elements("results") != null)
            {
                //Composing the search result from xml
                TermDefinition result = new TermDefinition()
                {
                    Term = doc.Element("results").Elements("result").First().Element("term").Value.ToString(),
                    TermPropertiesList
                    = (from _props in doc.Element("results").Elements("result")
                           //.Select<(tp => new TermProperties(tp.Element("definition").Value.ToString(), (PartOfSpeech)converter.ConvertBack(tp.Element("partofspeech").Value.ToString(), typeof(string), null, CultureInfo.CurrentCulture), tp.Element("example").Value.ToString())
                       select new TermProperties
                       {
                           Definition = _props.Element("definition").Value.ToString(),
                           Example = _props.Element("example").Value.ToString(),
                           PartOfSpeech = _props.Element("partofspeech").Value.ToString()
                       }).GroupBy(x => x.PartOfSpeech)
                         .Select(g => new Group<TermProperties, string>(g.Key, g)).ToList()
                };

                return result;
            }
            return default(TermDefinition);

            //TODO : Check if sth has failed.
        }

        public bool IsDataLoaded
        {
            get;
            private set;
        }

        /// <summary>
        /// Loads the RecentItems and FavouriteItems from isolated storage
        /// </summary>
        public async void LoadData()
        {
            var recent = await FileStorage.LoadAsync("recent.store");
            if (recent != null) this.RecentItems = recent;

            var favourites = await FileStorage.LoadAsync("favourites.store");
            if (favourites != null) this.FavouriteItems = favourites;

            this.IsDataLoaded = true;
        }
    }
}
